package cc.magicjson.spring.exploration.annotation.role.aop.analyze;


import cc.magicjson.spring.exploration.annotation.role.aop.application.service.DemoService;
import lombok.RequiredArgsConstructor;
import org.springframework.aop.Advisor;
import org.springframework.aop.support.AopUtils;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.util.stream.IntStream;

/**
 * 该分析器分析带有@Role(ROLE_INFRASTRUCTURE)与默认应用Bean
 * - 在依赖查找缓存检查时间对比
 * - 在内部编程式下Advisor是否真正被SpringAOP委托执行
 * 测试结果：
 * 1.时间上 模拟下看不出缓存提升 但可以看出@Role(ROLE_INFRASTRUCTURE)内部处理要更加复杂
 * 因为第一次加载时间相比过长
 * 2.不加@Role(ROLE_INFRASTRUCTURE)内部框架可能忽略该Advisor 导致无法正常通知
 * <p>
 * 分析结果：
 * Infrastructure advice - Before method execution: run
 * Is DemoService proxied? true
 * Is infrastructureAdvisor proxied? false
 * Is regularAdvisor proxied? false
 * Simulating cache check for infrastructureAdvisor
 * Infrastructure Advisor cache lookup time: 2000 ns
 * Infrastructure Advisor cache lookup time: 100 ns
 * Infrastructure Advisor cache lookup time: 100 ns
 * Infrastructure Advisor cache lookup time: 100 ns
 * Infrastructure Advisor cache lookup time: 100 ns
 * <p>
 * Simulating cache check for regularAdvisor
 * Regular Advisor cache lookup time: 200 ns
 * Regular Advisor cache lookup time: 200 ns
 * Regular Advisor cache lookup time: 200 ns
 * Regular Advisor cache lookup time: 100 ns
 * Regular Advisor cache lookup time: 100 ns
 * Infrastructure advice - Before method execution: doSomething
 * Doing something...
 * Infrastructure advice - After method execution: doSomething
 * Infrastructure advice - After method execution: run
 *
 * @author <a href="mailto:it_magicjson@163.com">MagicJson</a>
 */
@Component
@RequiredArgsConstructor
public class DemoAnalyzer implements CommandLineRunner {

    // CommandLineRunner 接口允许在 SpringApplication 运行完成后执行额外的代码

    // 注入 DemoService，用于演示和分析
    private final DemoService demoService;

    // 注入被 @Role(ROLE_INFRASTRUCTURE) 标记的 Advisor
    private final Advisor infrastructureAdvisor;


    // 注入普通的 Advisor，用于对比
    private final Advisor regularAdvisor;


    private Object getCachedAdvisor(Advisor advisor) {
        // 模拟缓存查找操作
        // 在实际应用中，这里可能会涉及复杂的缓存逻辑
        return advisor;
    }

    @Override
    public void run(String... args) {
        // CommandLineRunner 接口的 run 方法实现
        // 在应用启动后自动执行
        analyze();
        doSomething();
    }

    public void analyze() {
        // 分析方法，执行一系列检查和演示

        // 检查 DemoService 是否被代理
        System.out.println("Is DemoService proxied? " + AopUtils.isAopProxy(demoService));

        // 检查 infrastructureAdvisor 是否被代理
        System.out.println("Is infrastructureAdvisor proxied? " + AopUtils.isAopProxy(infrastructureAdvisor));

        // 检查 regularAdvisor 是否被代理
        System.out.println("Is regularAdvisor proxied? " + AopUtils.isAopProxy(regularAdvisor));

        // 模拟对 infrastructureAdvisor 的缓存检查
        System.out.println("Simulating cache check for infrastructureAdvisor");
        measureAdvisorCacheLookupTime(infrastructureAdvisor, "Infrastructure Advisor cache lookup time: ");

        // 添加对 regularAdvisor 的缓存检查
        System.out.println("\nSimulating cache check for regularAdvisor");
        measureAdvisorCacheLookupTime(regularAdvisor, "Regular Advisor cache lookup time: ");
    }

    private void measureAdvisorCacheLookupTime(Advisor infrastructureAdvisor, String description) {
        IntStream.range(0, 5)
            .mapToObj(i -> measureCacheLookupTime(infrastructureAdvisor))
            .forEach(time -> System.out.println(description + time + " ns"));
    }

    private long measureCacheLookupTime(Advisor advisor) {
        long start = System.nanoTime();
        getCachedAdvisor(advisor);
        long end = System.nanoTime();
        return end - start;
    }

    private void doSomething() {
        demoService.doSomething();
    }
}
